/**
 * Copyright (C) 2023 maminjie <canpool@163.com>
 * Copyright (C) 2017-2019 Uwe Kindler
 * SPDX-License-Identifier: LGPL-2.1
 **/

#include "QxDockFloatingWidgetTitleBar.h"
#include "QxDockElidingLabel.h"
#include "QxDockFloatingContainer.h"
#include "QxDockGlobal.h"
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QPixmap>
#include <QPushButton>
#include <QStyle>
#include <QToolButton>
#include <iostream>

QX_BEGIN_NAMESPACE

using tTabLabel = DockElidingLabel;
using tCloseButton = QToolButton;
using tMaximizeButton = QToolButton;

/**
 * @brief Private data class of public interface DockFloatingWidgetTitleBar
 */
struct DockFloatingWidgetTitleBarPrivate {
    DockFloatingWidgetTitleBar *_this;   ///< public interface class
    QLabel *IconLabel = nullptr;
    tTabLabel *TitleLabel;
    tCloseButton *CloseButton = nullptr;
    tMaximizeButton *MaximizeButton = nullptr;
    DockFloatingContainer *FloatingWidget = nullptr;
    eDragState DragState = DraggingInactive;
    QIcon MaximizeIcon;
    QIcon NormalIcon;
    bool Maximized = false;

    DockFloatingWidgetTitleBarPrivate(DockFloatingWidgetTitleBar *_public) : _this(_public)
    {
    }

    /**
     * Creates the complete layout including all controls
     */
    void createLayout();
};

void DockFloatingWidgetTitleBarPrivate::createLayout()
{
    TitleLabel = new tTabLabel();
    TitleLabel->setElideMode(Qt::ElideRight);
    TitleLabel->setText("dockWidget->windowTitle()");
    TitleLabel->setObjectName("floatingTitleLabel");
    TitleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    CloseButton = new tCloseButton();
    CloseButton->setObjectName("floatingTitleCloseButton");
    CloseButton->setAutoRaise(true);

    MaximizeButton = new tMaximizeButton();
    MaximizeButton->setObjectName("floatingTitleMaximizeButton");
    MaximizeButton->setAutoRaise(true);

    // The standard icons do does not look good on high DPI screens
    QIcon CloseIcon;
    QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
    CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
    CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
    CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
    CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    CloseButton->setVisible(true);
    CloseButton->setFocusPolicy(Qt::NoFocus);
    _this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));

    _this->setMaximizedIcon(false);
    MaximizeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    MaximizeButton->setVisible(true);
    MaximizeButton->setFocusPolicy(Qt::NoFocus);
    _this->connect(MaximizeButton, &QPushButton::clicked, _this, &DockFloatingWidgetTitleBar::maximizeRequested);

    QFontMetrics fm(TitleLabel->font());
    int Spacing = qRound(fm.height() / 4.0);

    // Fill the layout
    QBoxLayout *Layout = new QBoxLayout(QBoxLayout::LeftToRight);
    Layout->setContentsMargins(6, 0, 0, 0);
    Layout->setSpacing(0);
    _this->setLayout(Layout);
    Layout->addWidget(TitleLabel, 1);
    Layout->addSpacing(Spacing);
    Layout->addWidget(MaximizeButton);
    Layout->addWidget(CloseButton);
    Layout->setAlignment(Qt::AlignCenter);

    TitleLabel->setVisible(true);
}

DockFloatingWidgetTitleBar::DockFloatingWidgetTitleBar(DockFloatingContainer *parent)
    : QFrame(parent), d(new DockFloatingWidgetTitleBarPrivate(this))
{
    d->FloatingWidget = parent;
    d->createLayout();

    auto normalPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, d->MaximizeButton);
    d->NormalIcon.addPixmap(normalPixmap, QIcon::Normal);
    d->NormalIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);

    auto maxPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, d->MaximizeButton);
    d->MaximizeIcon.addPixmap(maxPixmap, QIcon::Normal);
    d->MaximizeIcon.addPixmap(internal::createTransparentPixmap(maxPixmap, 0.25), QIcon::Disabled);
    setMaximizedIcon(d->Maximized);
}

DockFloatingWidgetTitleBar::~DockFloatingWidgetTitleBar()
{
    delete d;
}

void DockFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev)
{
    if (ev->button() == Qt::LeftButton) {
        d->DragState = DraggingFloatingWidget;
        d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(), this);
        return;
    }
    Super::mousePressEvent(ev);
}

void DockFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
{
    d->DragState = DraggingInactive;
    if (d->FloatingWidget) {
        d->FloatingWidget->finishDragging();
    }
    Super::mouseReleaseEvent(ev);
}

void DockFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
{
    if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState) {
        d->DragState = DraggingInactive;
        Super::mouseMoveEvent(ev);
        return;
    }

    // move floating window
    if (DraggingFloatingWidget == d->DragState) {
        if (d->FloatingWidget->isMaximized()) {
            d->FloatingWidget->showNormal(true);
        }
        d->FloatingWidget->moveFloating();
        Super::mouseMoveEvent(ev);
        return;
    }
    Super::mouseMoveEvent(ev);
}

void DockFloatingWidgetTitleBar::enableCloseButton(bool Enable)
{
    d->CloseButton->setEnabled(Enable);
}

void DockFloatingWidgetTitleBar::setTitle(const QString &Text)
{
    d->TitleLabel->setText(Text);
}

void DockFloatingWidgetTitleBar::updateStyle()
{
    internal::repolishStyle(this, internal::RepolishDirectChildren);
}

void DockFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        emit maximizeRequested();
        event->accept();
    } else {
        QWidget::mouseDoubleClickEvent(event);
    }
}

void DockFloatingWidgetTitleBar::setMaximizedIcon(bool maximized)
{
    d->Maximized = maximized;
    if (maximized) {
        d->MaximizeButton->setIcon(d->NormalIcon);
    } else {
        d->MaximizeButton->setIcon(d->MaximizeIcon);
    }
}

void DockFloatingWidgetTitleBar::setMaximizeIcon(const QIcon &Icon)
{
    d->MaximizeIcon = Icon;
    if (d->Maximized) {
        setMaximizedIcon(d->Maximized);
    }
}

void DockFloatingWidgetTitleBar::setNormalIcon(const QIcon &Icon)
{
    d->NormalIcon = Icon;
    if (!d->Maximized) {
        setMaximizedIcon(d->Maximized);
    }
}

QIcon DockFloatingWidgetTitleBar::maximizeIcon() const
{
    return d->MaximizeIcon;
}

QIcon DockFloatingWidgetTitleBar::normalIcon() const
{
    return d->NormalIcon;
}

QX_END_NAMESPACE
